#!/usr/bin/env python3
"""
命令行界面模块
支持无头脚本执行和批量处理
"""
import argparse
import asyncio
import json
import sys
from pathlib import Path
from typing import List, Optional

from loguru import logger
from backend.script_manager import ScriptManager
from backend.executor import ScriptExecutor
from backend.models import ScriptModel, ExecutionResult
from config.settings import get_settings


class CLIManager:
    """命令行管理器"""
    
    def __init__(self):
        self.settings = get_settings()
        self.script_manager = ScriptManager()
        self.executor = ScriptExecutor()
        self.setup_logging()
    
    def setup_logging(self):
        """设置日志"""
        logger.add(
            self.settings.log_file,
            rotation="10 MB",
            retention="10 days",
            level=self.settings.log_level,
            format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}"
        )
    
    def list_scripts(self, status: Optional[str] = None):
        """列出脚本"""
        scripts = self.script_manager.list_scripts()
        
        if status:
            scripts = [s for s in scripts if s.status == status]
        
        if not scripts:
            print("没有找到脚本")
            return
        
        print(f"\n找到 {len(scripts)} 个脚本:")
        print("-" * 80)
        print(f"{'ID':<36} {'名称':<20} {'状态':<10} {'创建时间':<19}")
        print("-" * 80)
        
        for script in scripts:
            print(f"{script.id:<36} {script.name:<20} {script.status:<10} {script.created_at.strftime('%Y-%m-%d %H:%M:%S')}")
    
    async def execute_script(self, script_id: str, headless: bool = True) -> ExecutionResult:
        """执行脚本"""
        script = self.script_manager.get_script(script_id)
        if not script:
            print(f"脚本 {script_id} 不存在")
            return None
        
        print(f"开始执行脚本: {script.name}")
        
        # 设置执行环境
        env_vars = {
            'PLAYWRIGHT_HEADLESS': str(headless).lower(),
            'PLAYWRIGHT_TIMEOUT': str(self.settings.timeout)
        }
        
        try:
            result = await self.executor.execute_script(script, env_vars)
            
            # 输出结果
            print(f"\n执行完成:")
            print(f"  状态: {'成功' if result.success else '失败'}")
            print(f"  耗时: {result.duration:.2f}秒")
            
            if result.output:
                print(f"  输出: {result.output}")
            
            if result.error:
                print(f"  错误: {result.error}")
            
            return result
            
        except Exception as e:
            print(f"执行失败: {e}")
            logger.error(f"脚本执行失败: {e}")
            return None
    
    async def batch_execute(self, script_ids: List[str], headless: bool = True, 
                          max_concurrent: int = 3):
        """批量执行脚本"""
        print(f"开始批量执行 {len(script_ids)} 个脚本")
        
        # 创建信号量控制并发数
        semaphore = asyncio.Semaphore(max_concurrent)
        
        async def execute_with_semaphore(script_id: str):
            async with semaphore:
                return await self.execute_script(script_id, headless)
        
        # 并发执行
        tasks = [execute_with_semaphore(script_id) for script_id in script_ids]
        results = await asyncio.gather(*tasks, return_exceptions=True)
        
        # 统计结果
        successful = sum(1 for r in results if isinstance(r, ExecutionResult) and r.success)
        failed = len(results) - successful
        
        print(f"\n批量执行完成:")
        print(f"  成功: {successful}")
        print(f"  失败: {failed}")
        print(f"  总计: {len(results)}")
        
        return results
    
    def export_script(self, script_id: str, output_path: str):
        """导出脚本"""
        script = self.script_manager.get_script(script_id)
        if not script:
            print(f"脚本 {script_id} 不存在")
            return
        
        try:
            export_data = self.script_manager.export_script(script)
            
            output_file = Path(output_path)
            output_file.write_text(json.dumps(export_data, indent=2, ensure_ascii=False))
            
            print(f"脚本已导出到: {output_path}")
            
        except Exception as e:
            print(f"导出失败: {e}")
            logger.error(f"脚本导出失败: {e}")
    
    def import_script(self, file_path: str):
        """导入脚本"""
        try:
            import_file = Path(file_path)
            if not import_file.exists():
                print(f"文件不存在: {file_path}")
                return
            
            import_data = json.loads(import_file.read_text())
            script = self.script_manager.import_script(import_data)
            
            print(f"脚本已导入: {script.name} (ID: {script.id})")
            
        except Exception as e:
            print(f"导入失败: {e}")
            logger.error(f"脚本导入失败: {e}")
    
    def show_script_info(self, script_id: str):
        """显示脚本信息"""
        script = self.script_manager.get_script(script_id)
        if not script:
            print(f"脚本 {script_id} 不存在")
            return
        
        print(f"\n脚本信息:")
        print(f"  ID: {script.id}")
        print(f"  名称: {script.name}")
        print(f"  描述: {script.description or '无'}")
        print(f"  状态: {script.status}")
        print(f"  创建时间: {script.created_at.strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"  修改时间: {script.updated_at.strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"  断言数量: {len(script.assertions)}")
        
        if script.execution_stats:
            stats = script.execution_stats
            print(f"  执行统计:")
            print(f"    总次数: {stats.total_executions}")
            print(f"    成功次数: {stats.successful_executions}")
            print(f"    失败次数: {stats.failed_executions}")
            print(f"    成功率: {stats.success_rate:.1%}")
            print(f"    平均耗时: {stats.average_duration:.2f}秒")


def create_parser():
    """创建命令行解析器"""
    parser = argparse.ArgumentParser(
        description="UI自动化工具命令行界面",
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    
    subparsers = parser.add_subparsers(dest='command', help='可用命令')
    
    # 列出脚本
    list_parser = subparsers.add_parser('list', help='列出脚本')
    list_parser.add_argument('--status', choices=['active', 'archived', 'draft'], 
                           help='过滤脚本状态')
    
    # 执行脚本
    exec_parser = subparsers.add_parser('execute', help='执行脚本')
    exec_parser.add_argument('script_id', help='脚本ID')
    exec_parser.add_argument('--headless', action='store_true', default=True,
                           help='无头模式执行 (默认启用)')
    exec_parser.add_argument('--no-headless', dest='headless', action='store_false',
                           help='禁用无头模式')
    
    # 批量执行
    batch_parser = subparsers.add_parser('batch', help='批量执行脚本')
    batch_parser.add_argument('script_ids', nargs='+', help='脚本ID列表')
    batch_parser.add_argument('--headless', action='store_true', default=True,
                            help='无头模式执行 (默认启用)')
    batch_parser.add_argument('--no-headless', dest='headless', action='store_false',
                            help='禁用无头模式')
    batch_parser.add_argument('--max-concurrent', type=int, default=3,
                            help='最大并发数 (默认3)')
    
    # 导出脚本
    export_parser = subparsers.add_parser('export', help='导出脚本')
    export_parser.add_argument('script_id', help='脚本ID')
    export_parser.add_argument('output_path', help='输出文件路径')
    
    # 导入脚本
    import_parser = subparsers.add_parser('import', help='导入脚本')
    import_parser.add_argument('file_path', help='脚本文件路径')
    
    # 显示脚本信息
    info_parser = subparsers.add_parser('info', help='显示脚本信息')
    info_parser.add_argument('script_id', help='脚本ID')
    
    return parser


async def main():
    """主函数"""
    parser = create_parser()
    args = parser.parse_args()
    
    if not args.command:
        parser.print_help()
        return
    
    cli = CLIManager()
    
    try:
        if args.command == 'list':
            cli.list_scripts(args.status)
        
        elif args.command == 'execute':
            result = await cli.execute_script(args.script_id, args.headless)
            if result and not result.success:
                sys.exit(1)
        
        elif args.command == 'batch':
            results = await cli.batch_execute(args.script_ids, args.headless, 
                                            args.max_concurrent)
            # 如果有失败的脚本，返回错误码
            if any(isinstance(r, ExecutionResult) and not r.success for r in results):
                sys.exit(1)
        
        elif args.command == 'export':
            cli.export_script(args.script_id, args.output_path)
        
        elif args.command == 'import':
            cli.import_script(args.file_path)
        
        elif args.command == 'info':
            cli.show_script_info(args.script_id)
            
    except KeyboardInterrupt:
        print("\n用户中断操作")
        sys.exit(130)
    except Exception as e:
        print(f"执行失败: {e}")
        logger.error(f"CLI执行失败: {e}")
        sys.exit(1)


if __name__ == '__main__':
    asyncio.run(main())